package com.kg.fiber.service;

import java.util.Random;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.kg.fiber.common.TimedDoubleBuffer;
import com.kg.fiber.service.clock.Clocker;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j;

@Component
@Log4j
public class Simulator implements Runnable{
	
	@Setter @Getter
	private int singleNumber = 30000;
	
	@Setter @Getter
	private int singleInterval = 100;
	
	@Setter @Getter
	private double base = 0.465;
	
	@Setter @Getter
	private double scope = 0.0010;
	
	@Setter @Getter
	private double step = 0.00025;
	
	@Getter
	private boolean enabled = false;
	
	private Thread thread = null;
	
	private Random random = new Random();
			
	@Autowired
	private Clocker clock;
	
	@Autowired
	private Boss boss;
		
	//@Autowired
	//private Pci1714 pci;
	
	//@Autowired
	//private Pci1714DataHandler handler;
	
	private boolean stop = false;
	
	@PostConstruct
	private void postConstruct() {
		
		thread = new Thread(this);
		thread.setName("Simulator");
		thread.setDaemon(true);
		thread.start();
		
	}
	
	@PreDestroy
	private void preDestroy() {
		
		try {
			stop = true;
			thread.join();
		} catch (InterruptedException e) {
		} finally {
			thread = null;
		}
	}
	
	

	@Override
	public void run() {
		
		//long tm = clock.nowInMillis();
		
		while(!stop) {
			
			if(enabled) {
				
				
				int chCount = 1;
				
				long timestamp = clock.nowInMillis();
				
				TimedDoubleBuffer[] bs = new TimedDoubleBuffer[chCount];
				for(int i = 0; i < chCount; i++) {
					bs[i] = TimedDoubleBuffer.pool.get();
					bs[i].setTimestamp(timestamp);
				}
				
				for(int i = 0; i < singleNumber; i++) {
					int channel = i % chCount;
					bs[channel].add(newValue());
				}
				
				for(int i = 0; i < chCount; i++) {
					boss.feed(i, bs[i]);
				}
				
				
				/*
				Pci1714Config config = Pci1714Config.instance.get();
				int chCount = config.getChannelCount();
				
				Pci1714Data b = Pci1714Data.pool.get();
				
				double[] data = b.get(singleNumber);
				
				for(int i = 0; i < data.length; i++) {
					data[i] = newValue();
				}
				
				b.commit(data.length, tm, chCount);
				
				handler.feed(b);
				
				tm += singleInterval;
				
				*/
				
			}
			
			try {
				Thread.sleep(singleInterval);
			} catch(Exception e) {
				break;
			}
			
		}
		
	}
	
	public void upBase() {
		base += step;
	}
	
	public void downBase() {
		base -= step;
	}
	
	private double newValue() {
		
		if(random.nextBoolean())
			return base + random.nextDouble() * scope;
		else 
			return base - random.nextDouble() * scope;
		
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
		log.info("Set simulator function to " + enabled);
	}
	
	

}
